package com.esdk.utils;

import java.sql.Time;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

import com.esdk.esdk;
import lombok.NonNull;

/***
 * @author 范飞宇
 * @since 2003.?.?
 */
public class EasyTime {
	public final static String COMPACTDATE_FORMAT = "yyyyMMdd";
	public final static String COMPACTDATETIME_FORMAT = "yyyyMMddHHmmss";
	public final static String COMPACTDATETIME_FULL_FORMAT = "yyyyMMddHHmmssSSS";
	public final static String TIME_FORMAT = "HH:mm:ss";
	public final static String DATE_FORMAT = "yyyy-MM-dd";
	public final static String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	public final static String FULL_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS";
	public final static DateTimeFormatter FULL_FORMATTER=DateTimeFormatter.ofPattern(FULL_FORMAT);
	public final static String HK_DATE_FORMAT = "dd/MM/yyyy";
	public static final int DateMillSecond=1000*60*60*24;
	
	public static String calucateDurationDate(@NonNull Date begin,@NonNull Date end) {
		return calucateDurationDate(begin,end,null);
	}

	/**计算两个日期相隔的时间段*/
	public static String calucateDurationDate(@NonNull Date begin,@NonNull Date end,String format) {
		if(format==null)
			format="{}年{}月{}日";
		if(begin.compareTo(end)>0)
			return intervalTime(begin,end,Calendar.DATE)+"日";
		Integer[] params=new Integer[3];
		params[0]=intervalTime(begin,end,Calendar.YEAR);
		if(params[0]>0) {
			begin=addDate(begin,Calendar.YEAR,params[0]);
		}
		params[1]=intervalTime(begin,end,Calendar.MONTH);
		if(params[1]>0)
			begin=addDate(begin,Calendar.MONTH,params[1]);
		params[2]=intervalTime(begin,end,Calendar.DATE);
		return EasyStr.format(format,(Object[])params);
	}
	
	/**比较两个日期的相隔天数*/
	public static int dateDiff(@NonNull Date begin,@NonNull Date end) {
		return dateDiff(begin,end,'d');
	}

	/**比较两个日期的相隔天数(d)|月数(M)|年数(y)*/
	@SuppressWarnings("deprecation")
	public static int dateDiff(@NonNull Date begin,@NonNull Date end, char unit) {
		long sec =0;
		int result=-1;
		switch (unit){
		case Calendar.SECOND:	
		case 's':	
			sec = 1000; break;		
		case Calendar.MINUTE:	
		case 'm':	
			sec = 60000; break;		
		case Calendar.HOUR:		
		case 'h':	
		case 'H':	
			sec = 3600000; break;	
		case Calendar.DATE:		
		case 'd':		
		case Calendar.DAY_OF_WEEK:
		case Calendar.DAY_OF_YEAR:
			sec = 86400000; break;   //取得日期间隔,按时间单位算/24/60/60/1000	
		case Calendar.WEEK_OF_MONTH:
		case Calendar.WEEK_OF_YEAR:
		case 'w':
			sec = 604800000; break;   //按时间差取星期的间隔,每7天为一个星期/7/24/60/60/1000;
		case Calendar.YEAR:
		case 'y':
			result=end.getYear()-begin.getYear();
			if(end.getMonth()*100+end.getDate()<begin.getMonth()*100+begin.getDate())
				result-=1;
			return result;
		case Calendar.MONTH:
		case 'M':
			result=end.getMonth()-begin.getMonth();
			int v=end.getYear()-begin.getYear();
			if(v>0)
				result=v*12+result;
			if(end.getDate()<begin.getDate())
				result-=1;
			return result;
		default : sec =-1;
		}
		if (sec == -1) return -1;
		result=(int)((end.getTime() - begin.getTime())/sec);
		return result;
	}

	public static int networkDays(@NonNull Date begin,@NonNull Date end) {
		return networkDays(begin,end,new Date[] {});
	}
	
	/**比较两个日期的相隔的工作日天数（排除指定的假期）*/
	@SuppressWarnings("deprecation")
	public static int networkDays(@NonNull Date begin,@NonNull Date end, Date[] holidays) {
		int result=0;
		for(Date s=begin;s.getTime()<=end.getTime();s.setDate(s.getDate()+1)) {
			if(s.getDay()!=6&&s.getDay()!=0&&!EasyArray.contains(holidays,s))
				result++;
		}
		return result;
	}
	
	/**日期转指定格式字符串*/
	public static String toString(@NonNull Date date, @NonNull String format) {
		return format(date,format);
	}
	
	/**日期转指定格式字符串*/
	public static String toString(@NonNull Date date) {
		return format(date);
	}
	
	/**字符串转为日期类型*/
	public static Date toDate(@NonNull String datestr){
		return valueOf(datestr);
	}
	
	/**字符串转为timestamp类型*/
	public static Timestamp toTimeStamp(@NonNull String datestr){
		return new Timestamp(toDate(datestr).getTime());
	}
	
	/**字符串转为时间类型，例如：09:15:00*/
	@SuppressWarnings("deprecation")
	public static Time toTime(@NonNull String timestr){
		Integer[] time=esdk.math.toIntArray(timestr.split(":"));
		return new Time(time[0],time[1],time[2]);
	}

	/**字符串转为时间类型，例如：09:15:00*/
	@SuppressWarnings("deprecation")
	public static Time toTime(@NonNull Date date){
		return new Time(date.getHours(),date.getMinutes(),date.getSeconds());
	}
	
	/**字符串转为时间类型*/
	@SuppressWarnings("deprecation")
	public static Time toTime(int h,int m,int s){
		return new Time(h,m,s);
	}

	/**字符串转为时间类型*/
	@SuppressWarnings("deprecation")
	public static Time toTime(int h,int m){
		return new Time(h,m,0);
	}

	@SuppressWarnings("deprecation")
	public static LocalDate toLocalDate(@NonNull String datestr){
		return LocalDate.parse(datestr);
	}
	
	@SuppressWarnings("deprecation")
	public static LocalDateTime toLocalDateTime(@NonNull String dateTimeStr){
		return LocalDateTime.parse(dateTimeStr);
	}

	public static LocalDateTime toLocalDateTime(@NonNull Date date){
		LocalDateTime localDateTime = date.toInstant()
			.atZone(ZoneId.systemDefault())
			.toLocalDateTime();
		return localDateTime;
	}

	public static LocalDate toLocalDate(@NonNull Date date){
		LocalDate result;
		if(date instanceof java.sql.Date){
			result=LocalDate.parse(date.toString());
		}else{
			result=date.toInstant()
				.atZone(ZoneId.systemDefault())
				.toLocalDate();
		}
		return result;
	}

	/**防止java.sql.Date在toInstant()时出错，同时确保不受时区影响*/
	public static String formatToUTC(Date date){
		if(date ==null) return null;
		if(date instanceof java.sql.Date sqlDate)
			return format(sqlDate);
		else
			return format(date.toInstant().atZone(ZoneId.of("UTC")).toLocalDateTime());
	}

	public static Date toDate(@NonNull LocalDateTime localDateTime){
		Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
		return date;
	}
	public static Date toDate(@NonNull LocalDate localDate){
		Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());;
		return date;
	}
	/**字符串转为java.sql.date，去掉时间*/
	public static Date toSqlDate(String datestr,String format){
		if(esdk.str.isBlank(datestr))
			return null;
		Date d=toDate(datestr,format);
		return new java.sql.Date(d.getTime());
	}

	@SuppressWarnings("deprecation")
	public static java.sql.Date toSqlDate(Date d){
		if(d==null)
			return null;
		if(d instanceof java.sql.Date)
			return (java.sql.Date)d;
		return new java.sql.Date(d.getYear(),d.getMonth(),d.getDate());
	}
	
	/**字符串转为java.sql.date，去掉时间*/
	@SuppressWarnings("deprecation")
	public static java.sql.Date toSqlDate(@NonNull String datestr){
		String[] dateparams=datestr.split("-");
		return new java.sql.Date(Integer.valueOf(dateparams[0])-1900,Integer.valueOf(dateparams[1])-1,Integer.valueOf(dateparams[2]));
	}
	
	public static Date toDate(String dateString, String dateFormat) {
		if(esdk.str.isBlank(dateString))
			return null;
		SimpleDateFormat dd = new SimpleDateFormat(dateFormat);
		//String d = dd.format(new Date());
			try{
				Date date = dd.parse(dateString);
				return date;
			}
			catch(java.text.ParseException e){
				return null;
			}
	}

/**计算相隔时间数*/
	public static int intervalTime(@NonNull Date begin,@NonNull Date end,int calendarType){
		return dateDiff(begin,end,(char)calendarType);
	}
	
	/**计算相隔时间数*/
	public static long intervalTime(@NonNull Date begin,@NonNull Date end,int calendarType,boolean calculateTime){
		long result = 0;
		if (calculateTime || (calendarType == Calendar.SECOND)	|| (calendarType == Calendar.MINUTE)
				|| (calendarType == Calendar.HOUR)) {
			result = intervalTime(end,begin,calendarType);
			if (result >=0) return result; 
		}
		//不根据时间来
		switch (calendarType){
		case Calendar.DATE:		
		case Calendar.DAY_OF_WEEK:
		case Calendar.DAY_OF_YEAR:
			result = intervalDayNoTime(end,begin);
			break;
		case Calendar.WEEK_OF_MONTH:
		case Calendar.WEEK_OF_YEAR:
			result = intervalWeekNoTime(end,begin);
			break;
		case Calendar.MONTH:
			result = intervalMonth(end,begin);
			break;
		default : 
		
		}
		
		return result;
	}

	public static int intervalDayNoTime(@NonNull Date d1,@NonNull Date d2){
		//取日期,不计时间
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		Calendar c3 = Calendar.getInstance();
		c1.clear(); c2.clear();c3.clear();
		
		if (d1.after(d2)){
			c1.setTime(d2); c2.setTime(d1);
		}else{
			c1.setTime(d1); c2.setTime(d2);
		}
		int day =0;
		while (c1.get(Calendar.YEAR) < c2.get(Calendar.YEAR)){
			//设置到年底12月31号,Calendar.set中的月份参数从0开始,0为1月,11为12月
			c3.set(c1.get(Calendar.YEAR), 11, 31);  
			day = day + c3.get(Calendar.DAY_OF_YEAR) - c1.get(Calendar.DAY_OF_YEAR);
			c1.set(c1.get(Calendar.YEAR)+1, 0, 1);
		}
		day = day + c2.get(Calendar.DAY_OF_YEAR)- c1.get(Calendar.DAY_OF_YEAR);
		return day;
	}

	public static int intervalWeekNoTime(@NonNull Date d1,@NonNull Date d2){
		//按每周日为一周的开始计算周的间隔
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		Calendar c3 = Calendar.getInstance();
		c1.clear(); c2.clear(); c3.clear();
		if (d1.after(d2)){
			c1.setTime(d2); c2.setTime(d1);
		}else{
			c1.setTime(d1); c2.setTime(d2);
		}
		int week = 0;
		while (c1.get(Calendar.YEAR) < c2.get(Calendar.YEAR)){
			//设置到年底12月31号,Calendar.set中的月份从0开始,0为1月,11为12月
			c3.set(c1.get(Calendar.YEAR), 11, 31);  
			while (c3.get(Calendar.WEEK_OF_YEAR) == 1){  //与下年的1号在同一个星期内
				c3.set(Calendar.DATE, -4);
			}
			week = week + c3.get(Calendar.WEEK_OF_YEAR)- c1.get(Calendar.WEEK_OF_YEAR);
			c1.set(c1.get(Calendar.YEAR)+1, 0, 1);
		}
		week = week + c2.get(Calendar.WEEK_OF_YEAR)- c1.get(Calendar.WEEK_OF_YEAR);
		return week;
	}

	public static int intervalMonth(@NonNull Date d1,@NonNull Date d2) {
		// 取得月份间隔
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.clear(); c2.clear();
		c1.setTime(d1); c2.setTime(d2);
		
		int Year = Math.abs(c1.get(Calendar.YEAR)-c2.get(Calendar.YEAR));
		int Month = Math.abs(c1.get(Calendar.MONTH) - c2.get(Calendar.MONTH));
		return Year * 12 + Month;
	}

	public static Date createDate(int year,int month,int date) {
		return createDate(year,month,date,0,0,0);
	}
	
	@SuppressWarnings("deprecation") 
	public static java.sql.Date createSqlDate(int year,int month,int date) {
		if(year>1900)
			year=year-1900;
		return new java.sql.Date(year,month-1,date);
	}
	
	@SuppressWarnings("deprecation")
	public static Date createDate(int year,int month,int date,int hour,int minute,int second) {
		int millisecnd=hour==23&&minute==59&&second==59?999:0;
		return createDate(year,month,date,hour,minute,second,millisecnd);
	}

	@SuppressWarnings("deprecation")
	public static Date createDate(int year,int month,int date,int hour,int minute,int second,int millisecond) {
		Calendar cal= Calendar.getInstance();
		// 注意月份是从0开始的，所以1代表2月
//		cal.set(year, month-1, date,hour,minute,second);
		cal.set(year, month-1, date,hour,minute,second);
		cal.set(cal.MILLISECOND,millisecond);
		return cal.getTime();
	}
	
	public static String getNowTime() {
		return getNowTime(COMPACTDATETIME_FORMAT);
	}

	public static int getToday() {
		return getDayOfWeek(new Date());
	}
	
	public static String getNowTime(@NonNull String dateformat) {
		SimpleDateFormat formatter = new SimpleDateFormat(dateformat); // value="yyMMdd HHmmss"
		String result = formatter.format(new java.util.Date());
		formatter = null;
		return result;
	}

	/**注意，如果是java.sql.Date会先转换为java.utils.Date，否则会出错*/
	@SuppressWarnings("deprecation") 
	public static Date setTime(Date date,int hour,int minute,int second) {
		if(date==null)return null;
		if(date.getClass().equals(java.sql.Date.class))
			date=new Date(date.getTime());
		date.setHours(hour);
		date.setMinutes(minute);
		date.setSeconds(second);
		return date;
	}
	
	/**清除date的时间，即00:00:00,000*/
	public static Date clearTime(Date date) {
		return getStartDate(date);
	}

	public static Date toDateStart(LocalDate localDate){
		return esdk.obj.IFNotnull(localDate,EasyTime::toDate);
	}

	public static Date toDateEnd(LocalDate localDate){
		return esdk.obj.IFNotnull(localDate, (e) -> getEndDate(toDate(e)));
	}

	public static Date toDateStart(LocalDateTime localDateTime){
		return esdk.obj.IFNotnull(localDateTime,(e)->getStartDate(toDate(e)));
	}

	public static Date toDateEnd(LocalDateTime localDateTime){
		return esdk.obj.IFNotnull(localDateTime,(e)->getEndDate(toDate(e)));
	}

	/**清除date的时间，即00:00:00,000*/
	@SuppressWarnings("deprecation")
	public static Date getStartDate(Date date) {
		if(date==null)
			return date;
		else if(date instanceof java.sql.Date || date.getHours()==0 &&date.getMinutes()==0 && date.getSeconds()==0)
			return date;
		else {
			Calendar cal=Calendar.getInstance();
			cal.setTime(date);
			cal.set(Calendar.HOUR_OF_DAY,0);
			cal.set(Calendar.MINUTE,0);
			cal.set(Calendar.SECOND,0);
			cal.set(Calendar.MILLISECOND,0);
			return cal.getTime();
		}
	}
	
	/**获取date的最后一毫秒，即把时间写死为23:59:59,999*/
	public static Date getEndDate(Date d){
		if(d==null)
			return d;
		else {
			Calendar cal=Calendar.getInstance();
			cal.setTime(d);
			cal.set(Calendar.HOUR_OF_DAY,23);
			cal.set(Calendar.MINUTE,59);
			cal.set(Calendar.SECOND,59);
			cal.set(Calendar.MILLISECOND,999);
			return cal.getTime();
		}
	}
	
  public static String getStandardTimeFormat(Date date) {
  	return format(date);
 }
  
  private static String getFourYearTime(String value){
		if(value.matches("\\d{2}-.*")){
				return "20".concat(value);
		}else
			return value;
	}
  
  public static boolean isDate(@NonNull String value){
		return valueOf(value)!=null;
		
  }
  @SuppressWarnings("deprecation") public static Date valueOf(Object value){
  	if(value==null)
  		return null;
  	else if(value instanceof Date)
  		return (Date)value;
		else if(value instanceof LocalDate)
			return Date.from(((LocalDate)value).atStartOfDay(ZoneId.systemDefault()).toInstant());
		else if(value instanceof LocalDateTime)
			return Date.from(((LocalDateTime)value).atZone(ZoneId.systemDefault()).toInstant());
		else if(value instanceof String){
			String datestr=(String)value;
			if(EasyObj.isBlank(datestr))
				return null;
//			else if(datestr.matches("\\d+-\\d+-\\d+"))
//				return toSqlDate(datestr);
			String standardDateTime=null;
			if(datestr.indexOf("CST")>=0||datestr.indexOf("GMT")>=0) //CST:中国标准时间
				return new Date(datestr);
			else if(datestr.indexOf('/')>0)
				standardDateTime=convertHKDateTime(datestr);
			else
				standardDateTime=convertCSTDateTime(datestr);
			return toDate(standardDateTime,DATETIME_FORMAT);
		}
  	return null;
  }
  
  public static String getStandardTimeFormat(@NonNull String value) throws ParseException{
    if(value.trim().length()==0)
      throw new ParseException("日期不能为空");
    String originalvalue=value;
    //value=EasyStr.ReplaceAll(value,"/","-",false).trim();
    value=EasyStr.replaceAll(value,"  "," ",false,true);
    if((value==null||value.length()<8||value.length()>19)
        ||(value.length()==8&&value.indexOf("-")>=0&&value.indexOf("-0")>0)){
      throw new ParseException("日期:"+value+"格式有误,正确的格式:2004-09-22 00:00:00 ");
      // return "1900-01-01 00:00:00";
    }
    value=getFourYearTime(value);
    String result="1900-01-01 00:00:00";
    if(value.length()==8&&value.indexOf("-")<0)
      value=value.substring(0,4)+"-"+value.substring(4,6)+"-"+value.substring(6,8)+" 00:00:00";
    if(value.length()==19)
      return value;
    int ipos=0;
    String year=null;
    String month=null;
    String date=null;
    String hour=null;
    String minute=null;
    String second=null;
    try{
      ipos=value.indexOf("-");
      if(ipos>0){
        year=value.substring(0,ipos);
        value=value.substring(ipos+1,value.length());
        ipos=value.indexOf("-");
        month=EasyStr.insertZero(value.substring(0,ipos),2);
        value=value.substring(ipos+1,value.length());
        if(value.indexOf(" ")<0)
          value=value.concat(" ");
        ipos=value.indexOf(" ");
        date=EasyStr.insertZero(value.substring(0,ipos),2);
        value=value.substring(ipos+1,value.length());
      }
      else{
        year=value.substring(0,4);
        month=value.substring(4,6);
        date=value.substring(6,8);
        value=value.substring(8);
      }
      if(EasyMath.isNumeric(value)){
        hour=value.substring(0,2);
        minute=value.substring(2,4);
        second=value.substring(4,6);
      }
      else{
        ipos=value.indexOf(":");
        if(ipos>=0)
          hour=EasyStr.insertZero(value.substring(0,value.indexOf(":")),2);
        else
          hour="00";
        value=value.substring(value.indexOf(":")+1,value.length());
        ipos=value.indexOf(":");
        if(ipos>=0)
          minute=EasyStr.insertZero(value.substring(0,value.indexOf(":")),2);
        else if(value.length()>0)
          minute=EasyStr.insertZero(value.trim(),2);
        else
          minute="00";
        value=value.indexOf(":")>=0?value.substring(value.indexOf(":")+1,value.length()):"00";
        if(value.matches("[0-9,\\s]*"))//numeric and whitespace
          second=EasyStr.insertZero(value.trim(),2);
      }
      result=year.concat("-")+month.concat("-")+date.concat(" ")+hour.concat(":")+minute.concat(":")+second;
    }
    catch(Exception ex){
      throw new ParseException("日期格式有误"+originalvalue+":"+ex.toString()+".");
      //      return "1900-01-01 00:00:00";
    }
    return result;
  }
  /**CST是中国标准时间*/
  public static String convertCSTDateTime(@NonNull String value){
  	String result;//"2009-03-01 01:02:03"
  	String regex=value.indexOf("-")>=0?"(\\d{4})-?(\\d{1,2})-?(\\d{1,2}) ?(\\d{0,2}):?(\\d{0,2}):?(\\d{0,2})":"(\\d{4})(\\d{0,2})(\\d{0,2})(\\d{0,2})(\\d{0,2})(\\d{0,2})";
		try{
			result=esdk.regex.replaceAll(value,regex,m->{
				//System.out.println(EasyStr.concat(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5),m.group(6)));
				return EasyStr.concat(m.group(1),"-"
					,m.group(2).length()>0?EasyStr.insertZero(m.group(2),2):"01","-"
					,m.group(3).length()>0?EasyStr.insertZero(m.group(3),2):"01"," "
					,m.group(4)!=null?EasyStr.insertZero(m.group(4),2):"00",":"
					,m.group(5)!=null?EasyStr.insertZero(m.group(5),2):"00",":"
					,m.group(6)!=null?EasyStr.insertZero(m.group(6),2):"00");
			});
	  	return result;
		}catch(Exception e){
			throw new ParseRuntimeException(e.toString());
		}
  }
	
  public static String convertHKDateTime(@NonNull String value){
  	String result;//"01/03/2009 01:02:03"
		try{
			result=esdk.regex.replaceAll(value,"(\\d{1,2})/(\\d{1,2})/(\\d{4}) ?(\\d{0,2}):?(\\d{0,2}):?(\\d{0,2})",m->{
				//System.out.println(EasyStr.concat(m.group(1),m.group(2),m.group(3),m.group(4),m.group(5),m.group(6)));
				return EasyStr.concat(m.group(3),"-",m.group(2),"-",m.group(1)," "
					,m.group(4)!=null?EasyStr.insertZero(m.group(4),2):"00",":"
					,m.group(5)!=null?EasyStr.insertZero(m.group(5),2):"00",":"
					,m.group(6)!=null?EasyStr.insertZero(m.group(6),2):"00");
			});
	  	return result;
		}catch(Exception e){
			throw new ParseRuntimeException(e.toString());
		}
  }
  
	/**日期转指定格式字符串*/
  public static String format(Date date,boolean showTime) {
		if(date==null)return null;
		Instant instant=date.toInstant();
		LocalDateTime datetime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(showTime?DATETIME_FORMAT:DATE_FORMAT);
		return datetime.format(formatter);
  }
  
	/**日期转指定格式字符串，如果毫秒为0或时间为0，自动清除毫秒和时间。注意：返回的长度是不固定的*/
  public static String format(Date date) {
  	if(date==null)return null;
		if(date instanceof java.sql.Date sqldate){
				return sqldate.toString();
		}else{
			Instant instant=date.toInstant();
			LocalDateTime datetime=instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
			DateTimeFormatter formatter=DateTimeFormatter.ofPattern(FULL_FORMAT);
			String result=datetime.format(formatter);

			/*SimpleDateFormat sdf=new SimpleDateFormat(FULL_FORMAT);
			if(!(date instanceof Timestamp))
				sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
			String result=sdf.format(date);*/
			return result.replaceFirst("( 00:00:00)?\\.000","");
		}
  }

	public static String format(java.sql.Date date) {
		if(date==null)return null;
		return date.toString();
	}

	/**日期转指定格式字符串，如果毫秒为0或时间为0，自动清除毫秒和时间。注意：返回的长度是不固定的*/
	public static String format(LocalDateTime localDateTime) {
		if(localDateTime==null)return null;
		String result=localDateTime.format(FULL_FORMATTER);
		return result.replaceFirst("( 00:00:00)?\\.000","");
	}

	/**手工指定日期模板，格式化日期*/
  public static String format(Date date,@NonNull String pattern) {
  	if(date==null) return null;
		Instant instant=date.toInstant();
		LocalDateTime datetime = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
		return datetime.format(formatter);
  }
  /**判断时分秒是否为空，只是日期类型*/
  public static boolean isEmptyTime(Date date) {
		return (date.getTime()+TimeZone.getDefault().getRawOffset())%86400000==0;
  }
  
  /**日期增加天数，也可以用负数表示减少日期*/
	public static Date addDate(@NonNull Date date, int value) {
		return addDate(date,Calendar.DATE,value);
	}

	/**手工指定是时间计量单位（天数、月份、日期、时分秒）的增加或减少*/
	public static Date addDate(@NonNull Date date, int field, int value) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(field, value);
		if(date.getClass().equals(java.util.Date.class))
			return new java.util.Date(c.getTimeInMillis());
		else if(date.getClass().equals(java.sql.Date.class))
			return new java.sql.Date(c.getTimeInMillis());
		else if(date.getClass().equals(java.sql.Timestamp.class))
			return new java.sql.Timestamp(c.getTimeInMillis());
		else
			return c.getTime();
	}
  
	static public Date addDate(@NonNull Date date,int iYear,int iMonth,int iDate){
		GregorianCalendar newDate=new GregorianCalendar();
		newDate.setTime(date);
		newDate.add(GregorianCalendar.YEAR,iYear);
		newDate.add(GregorianCalendar.MONTH,iMonth);
		newDate.add(GregorianCalendar.DATE,iDate);
		return newDate.getTime();
	}
	
	static public Date addDate(@NonNull Date date,int iYear,int iMonth,int iDate,int iHour,int iMinute,int iSecond){
		GregorianCalendar newDate=new GregorianCalendar();
		newDate.setTime(date);
		newDate.add(GregorianCalendar.YEAR,iYear);
		newDate.add(GregorianCalendar.MONTH,iMonth);
		newDate.add(GregorianCalendar.DATE,iDate);
		newDate.add(GregorianCalendar.HOUR,iHour);
		newDate.add(GregorianCalendar.MINUTE,iMinute);
		newDate.add(GregorianCalendar.SECOND,iSecond);
		return newDate.getTime();
	}

	/**计算年龄（以当前日期为准）*/
	static public int computeAge(@NonNull Date birthday){
		 return computeAge(new Date(), birthday);
	}
	
	/**计算年龄*/
	@SuppressWarnings("deprecation")
	static public int computeAge(@NonNull Date now,Date birthday) {
		int age = now.getYear()-birthday.getYear();
		if(birthday.getMonth()>now.getMonth()||(birthday.getMonth()==now.getMonth()&&birthday.getDate()>now.getDate()))
			age--;
		return age;
	}
	
	/**格式化耗费时间*/
	public static String formatElapse(long ms) {
		long elapse=ms;
		String result="0毫秒";
		int SSS=(int)(elapse % 1000);
		if(SSS>0) {
			result=SSS+"毫秒";
		}
		if(SSS<elapse) {
			elapse=elapse/1000;
			int ss=(int)(elapse % 60);
			result=ss+"秒"+result;
			if(ss<elapse) {
				elapse=elapse/60;
				int mm=(int)(elapse % 60);
				result=mm+"分"+result;
				if(mm<elapse){
					elapse=elapse/60;
					int HH=(int)(elapse % 60);
					result=HH+"小时"+result;
					if(HH<elapse) {
						elapse=elapse/24;
						int dd=(int)(elapse % 24);
						result=dd+"天"+result;
					}
				}
			}
		}
		return result;
	}

	/**格式化耗费时间, hideTime 顺序为由小到大，即：毫秒->秒->分->时*/
	public static String formatElapse(long ms,boolean... showTime) {
		long elapse=ms;
		String result="";
		int SSS=(int)(elapse % 1000);
		if(showTime.length<1||showTime[0]) {
			if(SSS>0) 
				result=SSS+"毫秒";
		}
		if(SSS<elapse) {
			elapse=elapse/1000;
			int ss=(int)(elapse % 60);
			if(showTime.length<2||showTime[1]) {
				if(ss>0)
					result=ss+"秒"+result;
			}
			if(ss<elapse) {
				elapse=elapse/60;
				int mm=(int)(elapse % 60);
				if(showTime.length<3||showTime[2]) {
					result=mm+"分"+result;
				}
				if(mm<elapse){
					elapse=elapse/60;
					int HH=(int)(elapse % 60);
					if(showTime.length<4||showTime[4]) {
						result=HH+"小时"+result;
					}
					if(HH<elapse) {
						elapse=elapse/24;
						int dd=(int)(elapse % 24);
						result=dd+"天"+result;
					}
				}
			}
		}
		return result;
	}
	
	public static long time2sec(@NonNull String time) {
		long result=(long)esdk.time.addDate(esdk.time.toDate(time,"HH:mm:ss"),Calendar.HOUR,8).getTime()/1000; //23:59:59
		return result;
	}
	
	public static long time2sec(@NonNull String time,@NonNull String pattern) {
		int result=(int)esdk.time.addDate(esdk.time.toDate(time,pattern),Calendar.HOUR,8).getTime()/1000; //23:59:59
		return result;
	}

	public static String sec2time(long second) {
		return format(esdk.time.addDate(new Date(second*1000),Calendar.HOUR,-8),"HH:mm:ss");
	}

	public static String sec2time(long second,@NonNull String pattern) {
		return format(esdk.time.addDate(new Date(second*1000),Calendar.HOUR,-8),pattern);
	}
	
	@SuppressWarnings("deprecation") public static int getYear(@NonNull Date date) {
		return date.getYear()+1900;
	}
	
	@SuppressWarnings("deprecation") public static int getMonth(@NonNull Date date) {
		return date.getMonth()+1;
	}
	
	@SuppressWarnings("deprecation") public static int getYear() {
		return new Date().getYear()+1900;
	}
	
	@SuppressWarnings("deprecation") public static int getMonth() {
		return new Date().getMonth()+1;
	}
	
	@SuppressWarnings("deprecation") public static int getDate(@NonNull Date date) {
		return date.getDate();
	}
	
	public static int getHour(Date date) {
		return esdk.math.toInt(esdk.time.format(date,"H"));
	}
	
	/**获得星期几。周日：1，周六：7*/
	public static int getDayOfWeek(@NonNull Date date) {
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(cal.DAY_OF_WEEK);
	}

	 public static Date getFirstDateOfMonth(@NonNull Date date) {
		 Calendar cal = Calendar.getInstance();
		 cal.setTime(date);
		 cal.set(Calendar.DATE,1);
		 cal.set(Calendar.HOUR_OF_DAY,0);
		 cal.set(Calendar.MINUTE,0);
		 cal.set(Calendar.SECOND,0);
		 cal.set(Calendar.MILLISECOND,0);
		 return cal.getTime();
	 }

	 public static Date getLastDateOfMonth(@NonNull Date date) {
		 Date date1=new Date(date.getTime()/1000*1000);
		 date1=addDate(date1,Calendar.MONTH,+1);
		 date1.setDate(1);
		 date1.setHours(0);
		 date1.setMinutes(0);
		 date1.setSeconds(0);
		 date1=addDate(date1,Calendar.MILLISECOND,-1);
		 if(date.getClass().equals(java.sql.Date.class))
			 return toSqlDate(date1);
		 return date1;
	 }

	 /**获得本周一*/
	 @SuppressWarnings("deprecation")
	public static Date getFirstDateOfWeek(@NonNull Date date) {
		 Date d=addDate(date,1-date.getDay());
		 if(date.getClass().equals(java.sql.Date.class))
			 return toSqlDate(d);
		 else
			 return clearTime(d);
	 }

	 /**获得本周日的最后一秒*/
	 @SuppressWarnings("deprecation")
	public static Date getLastDateOfWeek(@NonNull Date date) {
	 Date d=addDate(date,7-date.getDay());
	 if(date.getClass().equals(java.sql.Date.class))
		 return toSqlDate(d);
	 else
		 return setTime(d,23,59,59);
	}

	public static Date getFirstDateOfYear(@NonNull Date date){
	 return createDate(getYear(date),1,1);
	}

	public static Date getLastDateOfYear(@NonNull Date date){
		return createDate(getYear(date),12,31,23,59,59);
	}

	public static String getBeforeMonth(@NonNull String dateformat,int value){
		return getAfterMonth(dateformat,-value);
	}

	public static String getAfterMonth(@NonNull String dateformat,int value){
		return getAfterTime(dateformat,Calendar.MONTH,value);
	}

	public static String getBeforeTime(@NonNull String dateformat,int date){
		return getAfterTime(dateformat,-date);
	}

	public static String getAfterTime(@NonNull String dateformat,int date){
		return getAfterTime(dateformat,Calendar.DATE,date);
	}

	public static String getAfterTime(@NonNull String dateformat,int field,int value){
		String result;
		java.text.SimpleDateFormat formatter=new java.text.SimpleDateFormat(dateformat); // value="yyMMdd HHmmss"
		Calendar cal=Calendar.getInstance();
		cal.add(field,value);
		result=formatter.format(cal.getTime());
		return result;
	}

	public static String getTime(@NonNull String dateFormat,long date){
		return format(new Date(date),dateFormat);
	}

	public static String getIntervalTime(String dateFormat,String formatTime,int field,int value) throws java.text.ParseException{
		java.text.SimpleDateFormat formatter=new java.text.SimpleDateFormat(dateFormat); // value="yyMMdd HHmmss"
		Date date=formatter.parse(formatTime);
		Calendar cal=Calendar.getInstance();
		cal.setTime(date);
		cal.add(field,value);
		String result=formatter.format(cal.getTime());
		return result;
	}

}
